#!/usr/bin/perl
use strict;
use GtfsField;
use GtfsFile;
use Gtfs;
use diagnostics;
use warnings;;

# A GTFS field/column definition, for generation ORM scaffolding.


# A GTFS field/column definition, for generation ORM scaffolding.


sub debug {
  my $msg = join(" ", @_);
  if($msg =~ /\n$/) {
    print $msg;
  } else {
    print $msg . "\n"; 
  }
}


sub genModel {
  my ($gtfsFile) = @_;
  my $clazz = $gtfsFile->class();

  print "#-------------------------------------------------------------------- \n";
  my $filename = "../gtfs/src/main/java/trs/gtfs/model/$clazz.java";
  print "$filename\n";

  my $java = "";
  $java .=  <<EOF1;
package trs.gtfs.model; 
import java.io.Serializable;
import java.util.Date;
public class $clazz implements Serializable {
EOF1
  # }

  my $fields = $gtfsFile->fields();
  foreach  my $gtfsField (@$fields) {
    my $type = $gtfsField->type();
    my $field = $gtfsField->name();
    $java .=  "  private $type $field;\n";
  }

  foreach  my $gtfsField (@$fields) {
    my $type = $gtfsField->type();
    my $field = $gtfsField->name();
    $java .=  "  /**  " . $gtfsField->description() . " */\n";
    $java .=  "  public $type " . $gtfsField->getter()  . "() { return this.$field; }\n";
    $java .=  "  public void " . $gtfsField->setter() . "($type $field) { this.$field = $field; }\n";
  }

  $java .= "public String toString() { \n";
  $java .= " StringBuilder buff = new StringBuilder();\n";
  $java .= " buff.append(\"" . $clazz . "[\");\n";
  foreach  my $gtfsField (@$fields) {
    my $field = $gtfsField->name();
    $java .= " buff.append(\", $field=\").append($field);\n";
  }
  $java .= " buff.append(\"]\");\n";
  $java .= " return buff.toString(); }\n";

  $java .=  "}\n";

  open(OUTFILE, '>', $filename);
  print OUTFILE $java;
  close(OUTFILE);

}



sub genFieldMapper {
  my ($gtfsFile) = @_;
  my $clazz = $gtfsFile->class();
  my $clazzFieldMapper= $clazz . "FieldMapper";
  my $clazzFieldDS = $clazz . "FieldDS";

  print "#-------------------------------------------------------------------- \n";
  my $filename = "../gtfs/src/main/java/trs/gtfs/mapper/$clazzFieldMapper.java";
  print "$filename\n";


  my $java = "";
$java .= <<EOF1;
package trs.gtfs.mapper; 
import trs.gtfs.model.$clazz; 
public class $clazzFieldMapper extends GtfsRowMapper<$clazz> {
  static abstract class $clazzFieldDS extends FieldDS<$clazz> { $clazzFieldDS(String name) { super(name); } }
EOF1
  # }

  my $fields = $gtfsFile->fields();

  my @fieldConstants = ();
  foreach  my $gtfsField (@$fields) {
    my $type = $gtfsField->type();
    my $field = $gtfsField->name();
    my $column = $gtfsField->column();

    push(@fieldConstants, uc($column));

    $java .= "  private static final $clazzFieldDS " . uc($column) . " = new $clazzFieldDS(\"$column\") {\t";
    $java .= "public void processColumn($clazz o, String value) {";
    if($type eq "String") {
      $java .= "      o." . $gtfsField->setter() . "(value); } };\n";
    } else {
      $java .= "      o." . $gtfsField->setter() . "(to" . ucfirst($type) . "(value)); } };\n";
    }
  }

  $java .= "  private static final $clazzFieldDS" . "[] allFields = new $clazzFieldDS" . "[] { " . join(",", @fieldConstants) . " };\n";

  $java .= "  public $clazzFieldMapper(String[] headers) { super(headers, allFields, new $clazzFieldDS" . "[headers.length]); }\n";
  $java .= "  \@Override\n";
  $java .= "  protected $clazz newRow() { return new $clazz(); }\n";
  $java .= "}\n";

#------------------------------------------------------------------------ 
  open(OUTFILE, '>', $filename);
  print OUTFILE $java;
  close(OUTFILE);
  #debug $java;
}

sub genClassParser {
  my ($gtfsFile) = @_;
  my $clazz = $gtfsFile->class();
  my $clazzFieldMapper= $clazz . "FieldMapper";
  my $clazzFieldDS = $clazz . "FieldDS";
  my $clazzParser = $clazz . "Parser";

  print "#-------------------------------------------------------------------- \n";
  my $filename = "../gtfs/src/main/java/trs/gtfs/parser/$clazzParser.java";
  print "$filename\n";


  my $java = "";

$java .=  <<EOF1;
package trs.gtfs.parser; 
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import trs.gtfs.mapper.$clazzFieldMapper;
import trs.gtfs.model.$clazz; 
public class $clazzParser extends GtfsParser<$clazz> {
  final List<$clazz> list = new LinkedList<$clazz>();
  protected $clazzFieldMapper getNewMapper(String[] headers) { return new $clazzFieldMapper(headers); }
  protected void processRow($clazz o) { list.add(o); } 
  public List<$clazz> getList() { return list; }
}
EOF1

#XXX Field Mappper - to take a "File Definition" class
#  FileDefinition<T> { T newRow();  FieldDS<T>[] getAllFields();
#XXX consider turning clazzParser into a "collector.".
#XXX then break inheritance with parser.
#XXX maybe have it accept a token list.
# }

#------------------------------------------------------------------------ 
  open(OUTFILE, '>', $filename);
  print OUTFILE $java;
  close(OUTFILE);
  #debug $java;
}

sub main(){
  my Gtfs $gtfs = Gtfs->new();;
  my @gtfsFiles = ();
  my $gtfsFile; # = GtfsFile->new();


  my %skipped = ();

	while(<STDIN>) {
		chomp(my $str = $_);
		if($str eq "") { next; }

    my ($file,$fieldId,$field,$required,@description) = split(/,/, $str);

    if($gtfs->isSupported($file) == 0) {
      if(not exists $skipped{$file}) {
        print STDERR "SKIP File:$file\n";
        $skipped{$file} = 1;
      }
      next;
    }

    if(!(defined $gtfsFile) || $file ne $gtfsFile->file()) {
      
      $gtfsFile = GtfsFile->new(
        file => $file,
        class => $gtfs->getClassName($file),
        pfx => $gtfs->getFieldPrefix($file)
      );

      #if($file ne "agency.txt") {
        my $fieldId = "feed_id";
        my GtfsField $gtfsField = GtfsField->new(
            name => "feedId",
            type => $gtfs->getFieldType($fieldId),
            column => "feed_id",
            db_type => $gtfs->getDBType($fieldId),
            required => 1,
            description => 'Feed Id is the field that uniquely identifies the feed source.'
        );
        $gtfsFile->addField($gtfsField);
      #}

      push(@gtfsFiles,$gtfsFile);
      debug "NEW File:" . $file . "\n";
    }

    if($gtfs->isFieldSupported($fieldId) == 0) {
      print STDERR "SKIP $file Field ||$fieldId||\n";
      next;
    } else {
      #debug "KEEP $file Field $fieldId\n";
    }

    #Canonical Column/Field names
    #$field =~ s/_field$//;
    my $column = $field;
    my $pfx = $gtfsFile->pfx();
    if($field =~ /$pfx/) {
      $field = substr($field, length($pfx));
    }
    my @toks = split(/_/, $field); 
    $field = shift(@toks);
    foreach my $str2 (@toks) {
      $field .= ucfirst($str2);
    }
   if($required eq "Required") {
     $required = 1;
   } else {
     $required = 0;
   }


    my GtfsField $gtfsField = GtfsField->new(
        name => $field,
        type => $gtfs->getFieldType($fieldId),
        column => $column,
        db_type => $gtfs->getDBType($fieldId),
        required =>  $required,
        description => join("," , @description)
    );
    #debug "$file field.name: " . $gtfsField->name() . 
           #" column: " . $gtfsField->column() . 
           #" db_type: " . $gtfsField->dbType() . "\n";
    $gtfsFile->addField($gtfsField);
  }

  print "---------------------------------\n";
  print "---------------------------------\n";
  print "---------------------------------\n";
  foreach  $gtfsFile (@gtfsFiles) {
    debug "CLASS:" . $gtfsFile->class() . "\n";

    my $fields = $gtfsFile->fields();
    foreach  my $gtfsField (@$fields) {
      debug "--field: " . ref($gtfsField) . ":" .
          "pojo: " . $gtfsField->type() . " " .  $gtfsField->name() . ":" .
          "\t" . $gtfsField->getter() . "\t" .  $gtfsField->getter() . ":" .
          "\tcolumn: " . $gtfsField->column() . " " . $gtfsField->dbType() . 
          "\t " . $gtfsField->required();
      debug "\t\t" . $gtfsField->description();

      genModel($gtfsFile);
      genFieldMapper($gtfsFile);
      genClassParser($gtfsFile);
    }
  }
}


#--------------------------------------------------------------------
&main();
1;
__END__

cat /tmp/gtfs.csv  | perl -w gtfsToJava.pl  
